package br.ufpi.controllers;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.Validations;
import br.ufpi.componets.UserSession;
import br.ufpi.componets.ValidateComponente;
import br.ufpi.model.User;
import br.ufpi.model.validacao.UsuarioValidacao;
import br.ufpi.repositories.UserRepository;
import br.ufpi.util.BaseUrl;
import br.ufpi.util.Criptografa;

@Resource
public class UserController extends BaseController {

	private final UserRepository usuarioRepository;
	private final UsuarioValidacao usuarioValidacao;
	private final HttpServletRequest request;

	public UserController(Result result, Validator validator, UserSession usuarioLogado, ValidateComponente validateComponente,
			UserRepository usuarioRepository, HttpServletRequest request, UsuarioValidacao usuarioValidacao) {
		super(result, validator, usuarioLogado, validateComponente);
		this.usuarioRepository = usuarioRepository;
		this.usuarioValidacao = usuarioValidacao;
		this.request = request;
	}

	@Get("/usuarios")
	public List<User> index() {
		return usuarioRepository.findAll();
	}

	@Post("/usuario/cadastrar")
	public void create(User user, String repeatPassWord) {
		usuarioValidacao.validarUsuario(user, repeatPassWord);
		validator.onErrorRedirectTo(UserController.class).cadastro(user);
		criptografarSenhaGerarConfimacaoEmail(user, true);
		usuarioRepository.create(user);
		result.include("success", "usuario.cadastrado.sucesso");
		BaseUrl.getInstance(request);
		String urlConfirmacao = BaseUrl.BASEURL + "/confirmar/" + user.getLogin().getTokenActive();
		// TODO Enviar email com confirmação de email
		result.redirectTo(this).cadastro(new User());
	}

	@Get("/usuario/cadastro")
	public User cadastro(User usuario) {
		usuario.getLogin().setPassword("");
		return usuario;
	}

	@Put("/usuarios")
	public void update(User usuario) {
		validate(usuario);
		User usuarioNovo = usuarioRepository.find(usuario.getId());
		if (!usuario.getLogin().getEmail().equals(usuarioNovo.getLogin().getEmail())) {
			if (usuarioRepository.isContainsEmail(usuario.getLogin().getEmail())) {
				validator.checking(new Validations() {
					{
						that(false, "email.cadastrado", "email.cadastrado");
					}
				});
			}
		}
		validator.onErrorUsePageOf(this).edit(usuarioNovo);
		usuarioNovo.setName(usuario.getName());
		usuarioNovo.setTelefone(usuario.getTelefone());
		if (!usuario.getLogin().getEmail().equals(usuarioNovo.getLogin().getEmail())) {
			usuarioNovo.getLogin().setEmail(usuario.getLogin().getEmail());
			criptografarSenhaGerarConfimacaoEmail(usuarioNovo, true);
			String urlConfirmacao = BaseUrl.BASEURL + "/confirmar/" + usuarioNovo.getLogin().getTokenActive();
			// TODO Enviar email de Confirmação
		}
		validator.validate(usuarioNovo);
		validator.onErrorUsePageOf(this).edit(usuarioNovo);
		usuarioRepository.update(usuarioNovo);
		usuarioLogado.setUser(usuarioNovo);
		result.redirectTo(LoginController.class).logado();
	}

	@Get("/usuarios/{usuario.id}/edit")
	public User edit(User usuario) {
		validate(usuario);
		User usuario1 = usuarioRepository.find(usuario.getId());
		return usuario1;
	}

	@Get("/usuario/alterarsenha")
	public void alterarsenha() {
	}

	@Post("/usuario/alterarSenha")
	public void alterarSenha(String senha, String confirmacaoSenha, String senhaAntiga) {
		validateComponente.validarString(senha, "login.novasenha");
		validateComponente.validarString(confirmacaoSenha, "login.confirmanovasenha");
		validateComponente.validarString(senhaAntiga, "login.senhaantiga");
		validator.onErrorRedirectTo(this).alterarsenha();
		if (senha.length() < 6) {
			validateComponente.gerarErro("senha.curta", "senha.curta");
			validator.onErrorRedirectTo(this).alterarsenha();
		}

		if (senha.equals(confirmacaoSenha)) {
			String senhaCriptografada = Criptografa.criptografar(senhaAntiga);
			if (senhaCriptografada.equals(usuarioLogado.getUser().getLogin().getPassword())) {
				User usuarioAtualizar = usuarioRepository.find(usuarioLogado.getUser().getId());
				usuarioAtualizar.getLogin().setPassword(Criptografa.criptografar(senha));
				usuarioRepository.update(usuarioAtualizar);
				usuarioLogado.setUser(usuarioAtualizar);
				result.include("sucesso", "login.alterarsenha.sucesso");
				result.redirectTo(this).alterarsenha();
			} else {
				validateComponente.gerarErro("login.alterarsenha.erroantigadiferente", "login.alterarsenha.erroantigadiferente");
				validator.onErrorRedirectTo(this).alterarsenha();
			}
		} else {
			validateComponente.gerarErro("login.alterarsenha.naoconfirma", "login.alterarsenha.naoconfirma");
			validator.onErrorRedirectTo(this).alterarsenha();
		}
	}

	@Get("/usuarios/{usuario.id}")
	public User show(User usuario) {
		validate(usuario);
		return usuarioRepository.find(usuario.getId());
	}

	@Delete("/usuarios/{usuario.id}")
	public void destroy(User usuario) {
		validate(usuario);
		usuarioRepository.destroy(usuarioRepository.find(usuario.getId()));
		result.redirectTo(this).index();
	}

	/**
	 * Usado pra analisar se usuario da section é o mesmo que e pra ter os dados
	 * alterados
	 * 
	 * @param usuario
	 */
	private void validate(User usuario) {
		if (usuario.getId() != usuarioLogado.getUser().getId())
			validateComponente.redirecionarHome("usuario.nao.pertimidido");
	}

	private void criptografarSenhaGerarConfimacaoEmail(User user, boolean confirmarPorEmail) {
		user.getLogin().setPassword(Criptografa.criptografar(user.getLogin().getPassword()));
		if (confirmarPorEmail) {
			do {
				user.getLogin().setTokenActive(Criptografa.criptografar(new Date().toString()));
			} while (usuarioRepository.isContainTokenActive(user.getLogin().getTokenActive()));
		}
	}

}